package com.xinyi.basic.base.dialog

import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.graphics.drawable.ColorDrawable
import android.os.Handler
import android.os.Message
import android.view.Gravity
import android.view.ViewGroup
import android.view.WindowManager
import android.view.animation.Animation
import androidx.annotation.FloatRange
import androidx.annotation.StyleRes
import com.xinyi.basic.thread.ThreadHandler

/**
 * @author 杨耿雷
 * @date 2024/9/30 16:20
 * @description Dialog基类
 */
abstract class BaseDialog: Dialog, Handler.Callback {

    /**
     * 在工作线程上进行处理的Handler
     */
    private var mThreadHandler: ThreadHandler? = null

    /**
     * @param context 上下文
     * @param cancelable 是否可以取消
     * @param cancelListener 添加取消监听
     */
    constructor(
        context: Context,
        cancelable: Boolean,
        cancelListener: DialogInterface.OnCancelListener
    ) : super(context, cancelable, cancelListener)

    /**
     * @param context 上下文
     * @param theme 主题
     */
    constructor(context: Context, theme: Int) : super(context, theme)

    /**
     * @param context 上下文
     */
    constructor(context: Context) : super(context)

    init {
        window?.attributes?.gravity = Gravity.CENTER
        window?.setBackgroundDrawable(ColorDrawable(0)) // 去除窗口透明部分显示的黑色
        initDialog()
    }

    private fun initDialog() {
        setCanceledOnTouchOutside(canceled())
        setCancelable(canceled())
        setGravity() // 统一默认重心为居中

        setDialogContentView()
        initViews()
        initParams()
        initListeners()
    }

    /**
     * 设置弹窗的内容视图
     */
    protected open fun setDialogContentView() {
        setContentView(initLayoutId())
    }

    /**
     * 设置 Dialog 宽度(WRAP_CONTENT/MATCH_PARENT)
     */
    fun setWidth(width: Int) {
        val params = window?.attributes
        params?.width = width
        window?.attributes = params
    }

    /**
     * 设置 Dialog 高度(WRAP_CONTENT/MATCH_PARENT)
     */
    fun setHeight(height: Int) {
        val params = window?.attributes
        params?.height = height
        window?.attributes = params
    }

    fun show(x: Int, y: Int) {
        onWindowAttributesChanged(
            x,
            y,
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT,
            Gravity.CENTER
        )
        show()
    }

    fun show(x: Int, y: Int, gravity: Int) {
        onWindowAttributesChanged(
            x,
            y,
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT,
            gravity
        )
        show()
    }

    /**
     * @param x 设置水平偏移
     * @param y 设置垂直偏移
     * @param width 宽
     * @param height 高
     * @param gravity 重心
     */
    private fun onWindowAttributesChanged(x: Int, y: Int, width: Int, height: Int, gravity: Int) {
        val params = window?.attributes
        params?.width = width
        params?.height = height
        params?.x = x
        params?.y = y
        params?.gravity = gravity
        onWindowAttributesChanged(params)
    }

    /**
     * 设置 Dialog 重心
     */
    open fun setGravity(gravity: Int = Gravity.CENTER) {
        window?.setGravity(gravity)
    }

    /**
     * 设置 Dialog 的动画
     */
    open fun setWindowAnimations(@StyleRes id: Int) {
        window?.setWindowAnimations(id)
    }

    /**
     * 设置窗口动画效果
     * @param animation 动画对象，用于定义窗口动画效果
     */
    open fun setWindowAnimations(animation: Animation) {
        // 设置窗口动画
        window?.setWindowAnimations(android.R.style.Animation_Dialog)
        window?.attributes?.windowAnimations = 0 // 防止双倍速度
        // 启动动画效果
        window?.decorView?.startAnimation(animation)
    }

    /**
     * 设置背景遮盖层开关(是否变暗)
     */
    fun setBackgroundDimEnabled(enabled: Boolean) {
        if (enabled) {
            window?.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
        } else {
            window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
        }
    }

    /**
     * 设置背景遮盖层的透明度（前提条件是背景遮盖层开关必须是为开启状态）
     */
    fun setBackgroundDimAmount(@FloatRange(from = 0.0, to = 1.0) dimAmount: Float) {
        window?.setDimAmount(dimAmount)
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        if (mThreadHandler == null) {
            mThreadHandler = ThreadHandler.createHandler(this)
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        try {
            mThreadHandler?.quit()
            mThreadHandler = null
        } catch (ex: Exception) {
            ex.printStackTrace()
        }
    }

    /**
     * 是否点击返回已经触摸屏幕空白区域关闭弹窗
     */
    open fun canceled(): Boolean {
        return true
    }

    /**
     * 初始化布局ID
     *
     * @return 返回ID
     */
    protected abstract fun initLayoutId(): Int

    /**
     * 初始化组件
     */
    protected open fun initViews() {}

    /**
     * 参数设置
     */
    protected open fun initParams() {}

    /**
     * 监听设置
     */
    protected open fun initListeners() {}

    /**
     * 处理消息
     */
    override fun handleMessage(msg: Message): Boolean {
        return false
    }

    /**
     * 在主线程上运行任务
     *
     * @param task 要执行的任务
     */
    @Synchronized
    fun runOnUiThread(task: Runnable?) {
        task ?: return
        mThreadHandler?.runOnUiThread(task)
    }

    /**
     * 在主线程上运行任务
     *
     * @param task 要执行的任务
     * @param duration 延迟执行的时间（毫秒）
     */
    @Synchronized
    fun runOnUiThread(task: Runnable?, duration: Long) {
        task ?: return
        mThreadHandler?.runOnUiThread(task, duration)
    }

    /**
     * 从主线程中移除指定的任务
     *
     * @param task 要移除的任务
     */
    @Synchronized
    fun removeFromUiThread(task: Runnable?) {
        task ?: return
        mThreadHandler?.removeFromUiThread(task)
    }

    /**
     * 将任务添加到队列中，在工作线程中执行
     *
     * @param task 要添加到队列中的任务
     */
    @Synchronized
    fun queueEvent(task: Runnable?) {
        task ?: return
        mThreadHandler?.queueEvent(task)
    }

    /**
     * 将任务添加到队列中，在工作线程中执行
     *
     * @param task 要添加到队列中的任务
     * @param delayMillis 延迟执行的时间（毫秒）
     */
    @Synchronized
    fun queueEvent(task: Runnable?, delayMillis: Long = 0) {
        task ?: return
        mThreadHandler?.queueEvent(task, delayMillis)
    }

    /**
     * 从队列中移除指定的任务
     *
     * @param task 要移除的任务
     */
    @Synchronized
    protected fun removeEvent(task: Runnable?) {
        task ?: return
        mThreadHandler?.removeEvent(task)
    }

    /**
     * 移除队列中的所有任务和消息
     */
    @Synchronized
    protected fun removeCallbacksAndMessages() {
        mThreadHandler?.removeCallbacksAndMessages()
    }

    /**
     * 发送消息到工作线程的消息队列中
     *
     * @param msg 要发送的消息对象
     */
    @Synchronized
    protected fun sendThreadMessageDelayed(msg: Message) {
        mThreadHandler?.sendThreadMessageDelayed(msg, 0)
    }

    /**
     * 发送线程消息/延迟
     *
     * @param msg 要发送的消息对象
     * @param delayMillis 延迟执行的时间（毫秒）
     */
    @Synchronized
    protected fun sendThreadMessageDelayed(msg: Message, delayMillis: Long = 0) {
        mThreadHandler?.sendThreadMessageDelayed(msg, delayMillis)
    }
}